package com.demo.rpc.netty.registry;

import com.demo.rpc.netty.protocol.InvocationProtocol;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class RegistryHandler extends ChannelInboundHandlerAdapter {

    private static Map<String, Object> registerMap = new ConcurrentHashMap<>();

    private List<String> classNames = new ArrayList<>();

    public RegistryHandler() {
        scanClass("com.demo.rpc.netty.provider");
        doRegister();
    }


    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        Object result = new Object();
        InvocationProtocol request = (InvocationProtocol) msg;
        if (registerMap.containsKey(request.getClassName())) {
            Object obj = registerMap.get(request.getClassName());
            result = obj.getClass().getMethod(request.getMethodName()).invoke(obj, request.getValues());
        }
        ctx.write(result);
        ctx.flush();
        ctx.close();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }

    private void doRegister() {
        //注册
        for (String className : classNames) {
            try {
                Class<?> aClass = Class.forName(className);
                Class<?> i = aClass.getInterfaces()[0];
                registerMap.put(i.getName(), aClass.newInstance());
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            }
        }
    }


    //扫描
    private void scanClass(String packageName) {
        URL resource = this.getClass().getClassLoader().getResource(packageName.replaceAll("\\.", "/"));
        File file = new File(resource.getFile());
        File[] files = file.listFiles();
        for (File f : files) {
            if (f.isDirectory()) {
                scanClass(packageName + "." + f.getName());
            } else {
                classNames.add(packageName + "." + f.getName().replace(".class",""));
            }
        }
    }


}
